package com.seo.service.user.recharge.impl;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import com.github.pagehelper.PageInfo;
import com.seo.function.PageTool;
import com.seo.mapper.user.account.AccountMapper;
import com.seo.mapper.user.recharge.RechargeMapper;
import com.seo.pojo.ReturnBody;
import com.seo.pojo.lightpay.LightPayCashier;
import com.seo.pojo.transaction.TransactionFlow;
import com.seo.service.business.impl.BusinessServiceImpl;
import com.seo.service.lightpay.sdk.LightPayService;
import com.seo.service.transaction.sdk.TransactionService;
import com.seo.service.user.recharge.sdk.RechargeService;
import com.seo.service.user.sdk.UserService;
import com.seo.utils.DataUtil;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service("rechargeService")
public class RechargeServiceImpl implements RechargeService {

	@Autowired
	private RechargeMapper rechargeMapper;

	@Autowired
	private TransactionService transactionService;

	@Autowired
	private AccountMapper accountMapper;

	@Autowired
	private UserService userService;

	@Autowired
	private PageTool pageTool;

	@Autowired
	private LightPayService lightPayService;

	@Autowired
	private BusinessServiceImpl businessService;

	@Autowired
	private ApplicationContext context;

	@PostConstruct
	public void init() {
		businessService.put("recharge", context.getBean(RechargeServiceImpl.class)::saveNotifyRecharge);
	}

	@Override
	public ReturnBody getRechargeDetailList(String tradeId, Map<String, Object> params) {
		ReturnBody rb = ReturnBody.init();
		String type = (String) params.get("type");
		if (StringUtils.isNotEmpty(type)) {
			String types = rechargeMapper.getRechargeType(type, 5);
			if (StringUtils.isEmpty(types)) {
				log.error("[{}]-充值列表,充值类型[{}]不存在", tradeId, type);
				return rb.error("充值类型不存在");
			}
			params.put("types", types);
		}
		PageInfo<?> page = pageTool.getAutoPage(rechargeMapper::getRechargeDetailList, params);
		rb.put("page", page);
		return rb.success();
	}

	@Override
	public ReturnBody saveArtificialRechargeDetail(String tradeId, Map<String, Object> params) {
		ReturnBody rb = ReturnBody.init();
		try {
			log.info("[{}]-查看用户是否存在", tradeId);
			if (!params.containsKey("userName")) {
				log.error("[{}]-用户名不能为空", tradeId);
				return rb.rollback("用户不能为空");
			}

			String userName = (String) params.get("userName");
			rb.run(userService.getUserByName(userName));
			if (!rb.isSuccess()) {
				return rb;
			}
			Integer userId = rb.get("userId", Integer.class);

			Map<String, Object> user = rb.get("user", String.class, Object.class);

			int parentId = (int) user.get("parentId");

			if (params.containsKey("parentId")) {
				int pId = (int) params.get("parentId");
				if (pId != parentId) {
					log.error("[{}]-只能选择自己的下级", tradeId);
					return rb.rollback("只能选择自己的下级");
				}
			}

			if (!params.containsKey("price")) {
				log.error("[{}]-充值金额不能为空", tradeId);
				return rb.rollback("充值金额不能为空");
			}

			BigDecimal price = DataUtil.getBigDecimal(params.get("price"));
			if (price.compareTo(BigDecimal.ZERO) <= 0) {
				return rb.error("充值金额不能小于0");
			}

			if (!params.containsKey("payMode")) {
				log.error("[{}]-支付类型不能为空", tradeId);
				return rb.rollback("支付类型不能为空");
			}
			String payMode = (String) params.get("payMode");
			String typeR = rechargeMapper.getRechargeType(payMode, 1);
			if (StringUtils.isEmpty(typeR)) {
				log.error("[{}]-支付类型不存在", tradeId);
				return rb.rollback("支付类型不存在");
			}
			if (!params.containsKey("remark")) {
				params.put("remark", "手动充值");
			}
			params.put("userId", userId);
			params.put("parentUserId", parentId);

			log.info("[{}]-插入账单明细", tradeId);
			rb.run(saveTransaction(tradeId, params, "recharge", TransactionFlow.State.finish.getValue()));
			if (!rb.isSuccess()) {
				return rb;
			}
			log.info("[{}]-增加用户余额，插入用户余额明细", tradeId);
			rb.run(saveBalanceDetail(tradeId, rb.get("tf", TransactionFlow.class)));
			if (!rb.isSuccess()) {
				return rb;
			}

			log.info("[{}]-插入用户充值明细", tradeId);
			Map<String, Object> bd = rb.get("bd", String.class, Object.class);
			params.put("balanceId", bd.get("id"));
			params.put("remark", bd.get("remark"));
			params.put("type", payMode);
			params.put("state", "01");
			int num = rechargeMapper.saveRechargeDetail(params);
			if (num == 0) {
				log.error("[{}]-插入充值明细-失败", tradeId);
				return rb.rollback();
			}
			return rb.success();
		} catch (Exception e) {
			log.error("异常-{}", e);
			return rb.rollback();
		} finally {
			rb.result();
		}
	}

	@Override
	public ReturnBody saveRecharge(String tradeId, Map<String, Object> params) {
		ReturnBody rb = ReturnBody.init();
		try {
			Integer userId = (Integer) params.get("userId");
			Map<String, Object> user = userService.getUserById(userId);
			if (user == null) {
				log.error("[{}]-用户不存在", tradeId);
				return rb.rollback();
			}
			if (!params.containsKey("price")) {
				log.error("[{}]-充值金额不能为空", tradeId);
				return rb.rollback("充值金额不能为空");
			}

			BigDecimal price = DataUtil.getBigDecimal(params.get("price"));
			if (price.compareTo(BigDecimal.ZERO) <= 0) {
				return rb.error("充值金额不能小于0");
			}

			String payMode = (String) params.get("payMode");
			String payType = (String) params.get("payType");
			String curDomain = (String) params.get("curDomain");
			LightPayCashier lpc = new LightPayCashier();

			lpc.setPayMode(payMode);
			lpc.setPayType(payType);
			lpc.setUserId(userId);
			params.put("parentUserId", user.get("parentId"));
			lpc.getOtherParams().putAll(params);

			rb.run(lightPayService.getCheckParams(tradeId, lpc));
			if (!rb.isSuccess()) {
				return rb;
			}

			if (!params.containsKey("remark")) {
				params.put("remark", "在线充值" + price + "元");
			}

			params.put("userId", userId);

			log.info("[{}]-插入账单明细", tradeId);
			rb.run(saveTransaction(tradeId, params, "recharge", TransactionFlow.State.no.getValue()));
			if (!rb.isSuccess()) {
				return rb;
			}

			TransactionFlow tf = rb.get("tf", TransactionFlow.class);
			lpc.setTransactionCode(tf.getCode());
			rb.run(lightPayService.saveLightPayCashier(tradeId, lpc));
			if (!rb.isSuccess()) {
				return rb.rollback(false, true);
			}

			return rb.success();
		} catch (Exception e) {
			log.error("异常-{}", e);
			return rb.rollback();
		} finally {
			rb.result();
		}
	}

	public ReturnBody saveTransaction(String tradeId, Map<String, Object> rd, String type, String state) {
		ReturnBody body = ReturnBody.init();

		TransactionFlow tf = new TransactionFlow();
		tf.setParentUserId((int) rd.get("parentUserId"));
		tf.setParentId(new Long(0));
		tf.setUserId((Integer) rd.get("userId"));
		tf.setAmount(DataUtil.getBigDecimal(rd.get("price")));
		tf.setPayAmount(DataUtil.getBigDecimal(rd.get("price")));
		tf.setAmountState(TransactionFlow.AmountState.in.getValue());
		tf.setRemark((String) rd.get("remark"));
		tf.setState(state);
		tf.setType(type);
		log.info("保存账单[{}]", tf);
		body.run(transactionService.saveTransactionFlow(tradeId, tf));
		if (!body.isSuccess()) {
			log.error("[{}]-【账单保存失败】", tradeId);
			return body;
		}

		if (tf.getPayAmount().compareTo(BigDecimal.ZERO) == 1) {
			body.run(transactionService.saveTransactionFlowItem(tradeId, tf, (String) rd.get("payMode"),
					tf.getPayAmount(), "amount", state));
			if (!body.isSuccess()) {
				log.error("[{}]-【账单科目[{}]保存失败】", tradeId, "amount");
				return body;
			}
		}
		body.put("tf", tf);
		return body.success();
	}

	public ReturnBody saveBalanceDetail(String tradeId, TransactionFlow tf) {
		ReturnBody rb = ReturnBody.init();
		Map<String, Object> params = new HashMap<>();
		params.put("userId", tf.getUserId());
		params.put("balance", tf.getAmount());
		params.put("type", "1");
		int num = accountMapper.updateUserBalance(params);
		if (num == 0) {
			log.error("[{}]-更新用户余额-失败", tradeId);
			return rb.rollback();
		}
		params.put("parentUserId", tf.getParentUserId());
		params.put("incomeState", "01");
		params.put("type", "recharge");
		params.put("remark", tf.getRemark());
		params.put("transactionId", tf.getId());
		params.put("state", "01");
		num = accountMapper.saveBalanceDetail(params);
		if (num == 0) {
			log.error("[{}]-保存用户余额明细-失败", tradeId);
			return rb.rollback();
		}
		rb.put("bd", params);
		return rb.success();
	}

	public ReturnBody saveNotifyRecharge(String tradeId, Map<String, Object> obj) {
		ReturnBody rb = ReturnBody.init();
		TransactionFlow tf = (TransactionFlow) obj.get("tf");
		rb.run(saveBalanceDetail(tradeId, tf));
		if (!rb.isSuccess()) {
			return rb;
		}
		String payMode = (String) obj.get("payMode");
		log.info("[{}]-插入用户充值明细", tradeId);
		Map<String, Object> bd = rb.get("bd", String.class, Object.class);
		Map<String, Object> params = new HashMap<>();
		params.put("userId", tf.getUserId());
		params.put("parentUserId", tf.getParentUserId());
		params.put("price", tf.getAmount());
		params.put("type", payMode);
		params.put("balanceId", bd.get("id"));
		params.put("remark", bd.get("remark"));
		params.put("state", "01");
		int num = rechargeMapper.saveRechargeDetail(params);
		if (num == 0) {
			log.error("[{}]-插入充值明细-失败", tradeId);
			return rb.rollback();
		}
		return rb.success();

	}

}
